package com.bolt.support.spring.jpa.jpql;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;

import static java.util.stream.Collectors.toList;

public interface SqlFunc <Children, R> extends Serializable {

    /**
     * 字段 IS not NULL or ！= ''
     * <p>例: isNull("name")</p>
     *
     * @param property    字段
     * @return children
     */
    Children isNotBlank(R property);

    /**
     * 字段 IS NULL or = ''
     * <p>例: isNull("name")</p>
     *
     * @param property    字段
     * @return children
     */
    Children isBlank(R property);

    /**
     * 字段 IS NULL
     * <p>例: isNull("name")</p>
     *
     * @param property    字段
     * @return children
     */
    Children isNull(R property);


    /**
     * 字段 IS NOT NULL
     * <p>例: isNotNull("name")</p>
     *
     * @param property    字段
     * @return children
     */
    Children isNotNull(R property);


    /**
     * 字段 IN (value.get(0), value.get(1), ...)
     * <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
     *
     * <li> 如果集合为 empty 则不会进行 sql 拼接 </li>
     *
     * @param property 执行条件
     * @param coll      数据集合
     * @return children
     */
    Children in( R property, Collection<?> coll);


    /**
     * 字段 IN (v0, v1, ...)
     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
     *
     * <li> 如果动态数组为 empty 则不会进行 sql 拼接 </li>
     *
     * @param property    字段
     * @param values    数据数组
     * @return children
     */
    default Children in( R property, Object... values) {
        return in(property, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{}))
                .collect(toList()));
    }


    Children notIn(R column, Collection<?> coll);

    /**
     * 字段 NOT IN (value.get(0), value.get(1), ...)
     * <p>例: notIn("id", Arrays.asList(1, 2, 3, 4, 5))</p>
     *
     * @param property    字段
     * @param values    数据数组
     * @return children
     */
    default Children notIn( R property, Object... values) {
        return notIn(property, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{}))
                .collect(toList()));
    }

    default Children orderByDesc(R... columns) {
        return orderBy(false, columns);
    }

    default Children orderByAsc(R... columns) {return orderBy(true, columns);}
    /**
     * 排序：ORDER BY 字段, ...
     * <p>例: orderBy(true, "id", "name")</p>
     *
     * @param isAsc     是否是 ASC 排序
     * @param columns   字段数组
     * @return children
     */
    Children orderBy( boolean isAsc, R... columns);





}

 